package com.mdc.mansion.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;


/**
 * RSA签名验签类
 */
public class RSASignature {
	private static Logger log = LoggerFactory.getLogger(RSASignature.class);
	
	/**
	 * 签名算法
	 */
	public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
	
	/**
	 * RSA签名
	 *
	 * @param content    待签名数据
	 * @param privateKey 商户私钥
	 * @param encode     字符集编码
	 * @return 签名值
	 */
	public static String sign(String content, String privateKey, String encode) {
		try {
			PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
			
			KeyFactory keyf = KeyFactory.getInstance("RSA");
			PrivateKey priKey = keyf.generatePrivate(priPKCS8);
			
			java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
			
			signature.initSign(priKey);
			signature.update(content.getBytes(encode));
			
			byte[] signed = signature.sign();
			
			return Base64.encode(signed);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return null;
	}
	
	public static String sign(String content, String privateKey) {
		try {
			PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
			KeyFactory keyf = KeyFactory.getInstance("RSA");
			PrivateKey priKey = keyf.generatePrivate(priPKCS8);
			java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
			signature.initSign(priKey);
			signature.update(content.getBytes());
			byte[] signed = signature.sign();
			return Base64.encode(signed);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * RSA验签名检查
	 *
	 * @param content   待签名数据
	 * @param sign      签名值
	 * @param publicKey 分配给开发商公钥
	 * @param encode    字符集编码
	 * @return 布尔值
	 */
	public static boolean doCheck(String content, String sign, String publicKey, String encode) {
		try {
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			byte[] encodedKey = Base64.decode(publicKey);
			PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
			
			
			java.security.Signature signature = java.security.Signature
					.getInstance(SIGN_ALGORITHMS);
			
			signature.initVerify(pubKey);
			signature.update(content.getBytes(encode));
			
			boolean bverify = signature.verify(Base64.decode(sign));
			return bverify;
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return false;
	}
	
	public static boolean doCheck(String content, String sign, String publicKey) {
		try {
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			byte[] encodedKey = Base64.decode(publicKey);
			PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
			
			java.security.Signature signature = java.security.Signature
					.getInstance(SIGN_ALGORITHMS);
			
			signature.initVerify(pubKey);
			signature.update(content.getBytes());
			
			boolean bverify = signature.verify(Base64.decode(sign));
			return bverify;
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return false;
	}
	
	
	//将请求参数转换成Map
	public static Map<String, String> getUrlParams(HttpServletRequest request) {
		String param = "";
		try {
			param = URLDecoder.decode(request.getQueryString(), "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		Map<String, String> result = new HashMap<>();
		String[] params = param.split("&");
		for (String s : params) {
			Integer index = s.indexOf("=");
			result.put(s.substring(0, index), s.substring(index + 1));
		}
		return result;
	}
	
	//从请求中获取所有参数
	public static SortedMap<String, String> getAllParams(HttpServletRequest request, Map<String, String> postParams) {
		SortedMap<String, String> result = new TreeMap<>();
		Map<String, String> urlParams = getUrlParams(request);
		for (Map.Entry entry : urlParams.entrySet()) {
			result.put((String) entry.getKey(), (String) entry.getValue());
		}
		if (postParams != null) {
			for (Map.Entry entry : postParams.entrySet()) {
				result.put((String) entry.getKey(), (String) entry.getValue());
			}
		}
		return result;
	}
	
	/**
	 * @param params 所有的请求参数都会在这里进行排序加密
	 * @return 得到签名
	 */
	public String getSign(SortedMap<String, String> params) {
		StringBuilder sb = new StringBuilder();
		for (Map.Entry entry : params.entrySet()) {
			if (!entry.getKey().equals("sign")) { //拼装参数,排除sign
				if (!StringUtils.isBlank(entry.getKey().toString()) && !StringUtils.isEmpty(entry.getValue().toString()))
					sb.append(entry.getKey()).append(entry.getValue());
			}
		}
		log.info("Before Sign : {}", sb.toString());
//		return DigestUtils.md5Hex(sb.toString()).toUpperCase();
		return null;
	}
	
	/**
	 * @param params 所有的请求参数都会在这里进行排序加密
	 * @return 验证签名结果
	 */
	public boolean verifySign(SortedMap<String, String> params) {
		if (params == null || StringUtils.isEmpty(params.get("sign"))) return false;
		String sign = getSign(params);
		log.info("verify Sign : {}", sign);
		return !StringUtils.isEmpty(sign) && params.get("sign").equals(sign);
	}
	
	
}